package cn.kennylee.codehub.common.das.validator;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;

/**
 * <p> 实现动态计算最大分页限制的Validator </p>
 * <p>Created on 2025/2/13.</p>
 *
 * @author kennylee
 * @since 0.0.1
 */
@Slf4j
public class MaxPageValidator implements ConstraintValidator<DynamicMaxPage, Object> {
    /**
     * 页码字段名
     */
    private String pageField;
    /**
     * 分页大小的字段名
     */
    private String sizeField;
    /**
     * 限制的最大可分页查询的记录数
     */
    private long totalRecords;

    @Override
    public void initialize(DynamicMaxPage constraintAnnotation) {
        this.pageField = constraintAnnotation.pageField();
        this.sizeField = constraintAnnotation.sizeField();
        this.totalRecords = constraintAnnotation.totalRecords();
    }

    /**
     * 验证页面逻辑
     *
     * @param validateBean 验证的入参，页码
     * @param context      context in which the constraint is evaluated
     * @return 是否验证通过
     */
    @Override
    public boolean isValid(Object validateBean, ConstraintValidatorContext context) {
        if (Objects.isNull(validateBean)) {
            // 由 @NotNull 单独处理
            log.debug("验证对象为空，验证通过");
            return true;
        }
        Long page = (Long) ReflectUtil.getFieldValue(validateBean, pageField);

        // 是否等于1，如果是1，直接返回true
        if (Objects.equals(page, 1L)) {
            return true;
        }

        Long size = (Long) ReflectUtil.getFieldValue(validateBean, sizeField);

        // 如果分页大小为空，返回验证失败
        if (Objects.isNull(page) || Objects.isNull(size) || size <= 0) {
            log.debug("分页大小或页码为空，验证失败");
            // 分页大小不合法
            return false;
        }

        try {
            // 计算最大页码
            long maxPage = (totalRecords + size - 1) / size;
            if (log.isDebugEnabled()) {
                log.debug("入参页码{}, 计算最大页码: {}", page, maxPage);
            }
            return page <= maxPage;
        } catch (Exception e) {
            log.error(StrUtil.format("计算最大页码失败，验证失败，错误信息: {}", e.getMessage()), e);
            return false;
        }
    }
}
